package com.sport.video.gateway.filter;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sport.video.common.dto.common.ResponseParams;
import com.sport.video.common.enums.RespEnum;
import com.sport.video.common.exception.BusinessException;
import com.sport.video.gateway.constant.FilterContant;
import com.sport.video.gateway.enums.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.util.WebUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class ErrorFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "error";
    }

    @Override
    public int filterOrder() {
        return -1;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.containsKey(FilterContant.THROWABLE);
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        ResponseParams response = new ResponseParams();
        try {
            Integer code = RespEnum.ERROR.code;
            String message = RespEnum.ERROR.msg;
            if (ctx.containsKey(FilterContant.THROWABLE)) {
                Throwable e = (Exception) ctx.get(FilterContant.THROWABLE);
                Throwable re = getOriginException(e);
                HttpServletRequest request = ctx.getRequest();
                if(re instanceof java.net.ConnectException){
                    message = "Real Service Connection refused";
                    log.warn("uri:{},error:{}" ,request.getRequestURI(),re.getMessage());
                }else if(re instanceof java.net.SocketTimeoutException){
                    message = "Real Service Timeout";
                    log.warn("uri:{},error:{}" ,request.getRequestURI(),re.getMessage());
                }else if(re instanceof com.netflix.client.ClientException){
                    message = re.getMessage();
                    log.warn("uri:{},error:{}" ,request.getRequestURI(),re.getMessage());
                }else if (re instanceof BusinessException){
                    message = ((BusinessException) re).getErrorMsg();
                    code = ((BusinessException) re).getErrorCode();
                    log.warn("Error during filtering",e);
                }
            }

            message = StrUtil.isBlank(message)?RespEnum.ERROR.msg:message;
            response.setRespCode(code);
            response.setRespMsg(message);
        } catch (Exception e) {
            String error = "Error during filtering[ErrorFilter]";
            log.error(error,e);
            response.setRespCode(RespEnum.ERROR.code);
            response.setRespMsg(RespEnum.ERROR.msg);
        }

        response.setTimestamp(DateUtil.current(false));
        response.setResultCode(ResultEnum.ERROR.code);
        response.setResultMsg(ResultEnum.ERROR.msg);
        HttpServletResponse servletResponse = ctx.getResponse();
        try {
            ServletOutputStream outputStream = servletResponse.getOutputStream();
            outputStream.write(JSON.toJSONString(response).getBytes());
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //避免zuul的其他过滤器再处理异常
        ctx.remove(FilterContant.THROWABLE);
        return null;
    }

    private Throwable getOriginException(Throwable e){
        if (null == e){
            return null;
        }

        e = e.getCause();
        while(null != e.getCause()){
            e = e.getCause();
        }
        return e;
    }

}
